x11: Set background color bypassing colormaps
authorBenjamin Otte <otte@redhat.com>
Sun, 29 Aug 2010 09:52:29 +0000 (11:52 +0200)
committerBenjamin Otte <otte@redhat.com>
Sun, 26 Sep 2010 13:11:33 +0000 (15:11 +0200)
Direct and TrueColor visuals don't alloc colors, so they don't need to
fiddle with colormaps. Just copy the code that computes the pixel value
from gdkcolor-x11.c and use it. For other visual types, don't set the
background color and fallback to background = None.

gdk/x11/gdkwindow-x11.c

index 0b1f4855160ba6fca57a2dbef68a1925f0320ead..fecaefc53f0c7d8b6fc2518329efbb95e74c75de 100644 (file)
@@ -2612,21 +2612,59 @@ gdk_window_set_transient_for (GdkWindow *window,
                          GDK_WINDOW_XID (parent));
 }
 
-static void
+static gboolean
 gdk_window_x11_set_back_color (GdkWindow *window,
-                               GdkColor *color)
+                               double     red,
+                               double     green,
+                               double     blue,
+                               double     alpha)
 {
-  GdkColor allocated = *color;
+  GdkVisual *visual = gdk_window_get_visual (window);
 
-  if (!gdk_colormap_alloc_color (gdk_drawable_get_colormap (window),
-                                 &allocated,
-                                 TRUE, TRUE))
-    return;
+  /* I suppose we could handle these, but that'd require fiddling with 
+   * xrender formats... */
+  if (alpha != 1.0)
+    return FALSE;
 
-  XSetWindowBackground (GDK_WINDOW_XDISPLAY (window),
-                       GDK_WINDOW_XID (window), allocated.pixel);
+  switch (visual->type)
+    {
+    case GDK_VISUAL_DIRECT_COLOR:
+    case GDK_VISUAL_TRUE_COLOR:
+       {
+         /* If bits not used for color are used for something other than padding,
+          * it's likely alpha, so we set them to 1s.
+          */
+         guint padding, pixel;
+
+         /* Shifting by >= width-of-type isn't defined in C */
+         if (visual->depth >= 32)
+           padding = 0;
+         else
+           padding = ((~(guint32)0)) << visual->depth;
+         
+         pixel = ~ (visual->red_mask | visual->green_mask | visual->blue_mask | padding);
+         
+         pixel += (((int) (red   * ((1 << visual->red_prec  ) - 1))) << visual->red_shift  ) +
+                  (((int) (green * ((1 << visual->green_prec) - 1))) << visual->green_shift) +
+                  (((int) (blue  * ((1 << visual->blue_prec ) - 1))) << visual->blue_shift );
 
-  gdk_colormap_free_colors (gdk_drawable_get_colormap (window), &allocated, 1);
+          XSetWindowBackground (GDK_WINDOW_XDISPLAY (window),
+                                GDK_WINDOW_XID (window), pixel);
+       }
+      return TRUE;
+
+    /* These require fiddling with the colormap, and as they're essentially unused
+     * we're just gonna skip them for now.
+     */
+    case GDK_VISUAL_PSEUDO_COLOR:
+    case GDK_VISUAL_GRAYSCALE:
+    case GDK_VISUAL_STATIC_GRAY:
+    case GDK_VISUAL_STATIC_COLOR:
+    default:
+      break;
+    }
+
+  return FALSE;
 }
 
 static gboolean
@@ -2641,7 +2679,6 @@ static void
 gdk_window_x11_set_background (GdkWindow      *window,
                                cairo_pattern_t *pattern)
 {
-  GdkColor color = { 0, };
   double r, g, b, a;
   cairo_surface_t *surface;
   cairo_matrix_t matrix;
@@ -2660,9 +2697,8 @@ gdk_window_x11_set_background (GdkWindow      *window,
     {
     case CAIRO_PATTERN_TYPE_SOLID:
       cairo_pattern_get_rgba (pattern, &r, &g, &b, &a);
-      color.red = r * 65535;
-      color.green = g * 65535;
-      color.blue = b * 65535;
+      if (gdk_window_x11_set_back_color (window, r, g, b, a))
+        return;
       break;
     case CAIRO_PATTERN_TYPE_SURFACE:
       cairo_pattern_get_matrix (pattern, &matrix);
@@ -2692,7 +2728,8 @@ gdk_window_x11_set_background (GdkWindow      *window,
       break;
     }
 
-  gdk_window_x11_set_back_color (window, &color);
+  XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
+                              GDK_WINDOW_XID (window), None);
 }
 
 static void